<template>
  <div class="wrapper">
    <div
      class="node-item"
      v-for="item in nodes"
      :key="item.ID"
      :style="calcNodeAttrs(item)"
      :data-nid="item.ID"
    >
      {{ item.Name }}
    </div>
    <span
      class="note"
      v-for="label in labels"
      :key="label.MyPK"
      :style="calcLabelAttrs(label)"
      >{{ label.Name }}</span
    >
  </div>
</template>


<script>
import { jsPlumb } from "jsplumb";
import { HttpHandler } from "../../api/Gener";

// 引用流程图配置，详情见TrackConfig文件
import {
  STYLE_NODE_COLOR_FORE_TRACK,
  STYLE_NODE_COLOR_FORE_HOVER,
  STYLE_NODE_BORDER_COLOR_END,
  STYLE_NODE_BORDER_COLOR_FIRST,
  STYLE_NODE_BORDER_RADIUS,
  STYLE_NODE_DEFAULT_ICON,
  STYLE_NODE_DEFAULT_ICON_PATH,
  STYLE_NODE_BORDER_WIDTH_NORMAL, //节点边框宽度
  STYLE_NODE_BORDER_WIDTH_HOVER,
  STYLE_NODE_BORDER_COLOR, //节点边框鼠标悬停时的宽度
} from "../../config/TrackConfig";

export default {
  name: "v-js-plumb",
  data() {
    return {
      // 节点列表
      nodes: [],
      // 节点方向
      nodeDirection: [],
      // 标签信息
      labels: [],
    };
  },
  methods: {
    calcLabelAttrs(label) {
      return {
        top: `${label.Y}px`,
        left: `${label.X}px`,
      };
    },

    // 计算节点属性
    calcNodeAttrs(node) {
      return {
        top: `${node.Y}px`,
        left: `${node.X}px`,
        ...node.style,
      };
    },
    // 绘制节点
    fetchData() {
      const { FK_Flow, WorkID = 0, FID = 0, Token } = this.$route.query;
      const handler = new HttpHandler("BP.WF.HttpHandler.WF_WorkOpt_OneWork");
      handler.AddPara("FK_Flow", FK_Flow);
      handler.AddPara("WorkID", WorkID);
      handler.AddPara("FID", FID);
      if (Token) handler.AddPara("Token", token);
      let flowData = handler.DoMethodReturnString("Chart_Init");
      if (typeof flowData === "string") {
        if (flowData.indexOf("err@") == 0) {
          this.$message.error(flowData.place("err@", ""));
          return;
        }
        flowData = JSON.parse(flowData);
      }
      this.nodes = this.analyNodes(flowData.WF_Node) || [];
      this.nodeDirection = flowData.WF_Direction || [];
      this.labels = flowData.WF_LabNote || [];
      this.drawNodesAnchor();
    },
    // 绘制节点关系，节点位置通过template绘制，后续的连接线通过此方法生成
    async drawNodesAnchor() {
      await this.$nextTick();
      const { nodeDirection } = this;
      let plumbInstance = jsPlumb.getInstance();
      plumbInstance.ready(() => {
        for (let node of nodeDirection) {
          plumbInstance.connect({
            source: document.querySelector(`div[data-nid="${node.Node}"]`),
            target: document.querySelector(`div[data-nid="${node.ToNode}"]`),
            anchor: [
              "Left",
              "Right",
              "Top",
              "Bottom",
              [0.3, 0, 0, -1],
              [0.7, 0, 0, -1],
              [0.3, 1, 0, 1],
              [0.7, 1, 0, 1],
            ],
            connector: ["StateMachine"],
            endpoint: "Blank",
            overlays: [["Arrow", { width: 8, length: 8, location: 1 }]],
            paintStyle: { stroke: "#909399", strokeWidth: 2 },
          });
        }
      });
    },

    // 计算边框颜色
    getNodeBorderColor(val, startVal, endVal) {
      return val === startVal
        ? STYLE_NODE_BORDER_COLOR_FIRST
        : val === endVal
        ? STYLE_NODE_BORDER_COLOR_END
        : STYLE_NODE_BORDER_COLOR;
    },

    // 分析节点
    analyNodes(nodes) {
      // 处理border颜色
      const startVal = 0; // 最小节点值
      const endVal = Math.max(...nodes.map((node) => node.NodePosType)); // 最大节点值
      for (const node of nodes) {
        const color = this.getNodeBorderColor(
          node.NodePosType,
          startVal,
          endVal
        );
        node.style = {
          border: `${STYLE_NODE_BORDER_WIDTH_NORMAL}px solid ${color}`,
        };
      }
      return nodes;
    },
  },
  mounted() {
    // load data
    this.fetchData();
    // draw nodes
  },
};
</script>

<style lang="less" scoped>
.wrapper {
  width: 800px;
  height: 600px;
  box-sizing: border-box;
  position: relative;
  .node-item {
    width: 100px;
    height: 40px;
    line-height: 40px;
    text-align: center;
    border: 1px solid #cccccc;
    border-radius: 4px;
    margin: 12px;
    background: #ffffff;
    position: absolute;
  }
  .note {
    position: absolute;
    color: #031f5d;
    white-space: nowrap;
  }
}
</style>